package com.xyy.saas.payment.api.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.xyy.saas.payment.adpater.RouteManager;
import com.xyy.saas.payment.common.Constants;
import com.xyy.saas.payment.common.exception.PaymentException;
import com.xyy.saas.payment.cores.api.EntrustPayApi;
import com.xyy.saas.payment.cores.bo.EntrustBO;
import com.xyy.saas.payment.cores.bo.EntrustPayBO;
import com.xyy.saas.payment.cores.bo.PrepayBo;
import com.xyy.saas.payment.cores.enums.EntrustStatusEnum;
import com.xyy.saas.payment.cores.enums.ResultCodeEnum;
import com.xyy.saas.payment.cores.vo.EntrustPayVO;
import com.xyy.saas.payment.cores.vo.EntrustVO;
import com.xyy.saas.payment.cores.vo.ResultVO;
import com.xyy.saas.payment.dao.model.EntrustPayInfo;
import com.xyy.saas.payment.entrust.bo.EntrustInfoBo;
import com.xyy.saas.payment.entrust.core.dto.EntrustPayDto;
import com.xyy.saas.payment.entrust.core.dto.EntrustPayInfoDto;
import com.xyy.saas.payment.payment.core.dto.PrepayDto;
import com.xyy.saas.payment.payment.core.service.PaymentService;
import com.xyy.saas.payment.service.EntrustPayInfoService;
import com.xyy.saas.payment.service.PayAccountService;
import com.xyy.saas.payment.util.JSONUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

/**
 * 委托代扣接口(签约代扣) 实现
 */
@Slf4j
@Service(version = "1.0.0")
public class EntrustPayApiImpl implements EntrustPayApi {

    @Autowired
    private RouteManager routeManager;

    @Autowired
    private PayAccountService payAccountService;

    @Autowired
    private PaymentService paymentService;

    @Autowired
    private EntrustPayInfoService entrustPayInfoService;

    @Override
    public ResultVO entrustSign(EntrustVO entrustVO) {
        log.info("EntrustPayApiImpl entrust sign start param:{}", JSONUtils.toJSON(entrustVO));
        try {
            // 参数校验
            ResultVO resultVO = checkEntrust(entrustVO);
            if(!ResultCodeEnum.SUCCESS.getCode().equalsIgnoreCase(resultVO.getCode())) {
                throw new PaymentException(resultVO.getMsg());
            }
            // 转换签约信息
            String accountId = payAccountService.getAccountIdByBusiness(entrustVO.getBusinessOrderType(), entrustVO.getBusinessUserId());
            if(StringUtils.isBlank(accountId)) {
                log.info("EntrustPayApiImpl account info is not found. entrustPayVO:{}", JSONUtils.toJSON(entrustVO));
                return ResultVO.createError("无收款方信息!");
            }

            EntrustPayInfoDto entrustPayInfo = new EntrustPayInfoDto();
            entrustPayInfo.setBusinessType(entrustVO.getBusinessType());
            entrustPayInfo.setCallback(entrustVO.getCallback());
            entrustPayInfo.setPlanId(entrustVO.getPlanId());
            entrustPayInfo.setSignOrderNo(entrustVO.getSignOrderNo());
            entrustPayInfo.setSignUserId(entrustVO.getSignUserId());
            entrustPayInfo.setSignMode(entrustVO.getSignMode().getMode());
            entrustPayInfo.setChannel(entrustVO.getChannel().getCode());
            entrustPayInfo.setAccountId(accountId);
            entrustPayInfo.setContractDisplayAccount(entrustVO.getContractDisplayAccount());
            entrustPayInfo.setClientIp(entrustVO.getClientIp());
            EntrustBO entrustBO = this.routeManager.entrustSign(entrustPayInfo);
            log.info("EntrustPayApiImpl entrust sign end result:{}", JSONUtils.toJSON(entrustBO));
            return ResultVO.createSuccess(entrustBO);
        } catch (Exception e) {
            log.error("EntrustPayApiImpl#entrustSign error. error:{}", e);
            return ResultVO.create(ResultCodeEnum.DEFAULT_ERROR);
        }
    }

    private ResultVO checkEntrust(EntrustVO entrustVO) {
        if(null == entrustVO) {
            return ResultVO.createError("参数为空!");
        }
        if(StringUtils.isBlank(entrustVO.getBusinessType())) {
            return ResultVO.createError("业务线标识为空");
        }
        if(StringUtils.isBlank(entrustVO.getBusinessOrderType())) {
            return ResultVO.createError("业务订单类型");
        }
        if(null == entrustVO.getSignMode()) {
            return ResultVO.createError("签约方式为空!");
        }
        if(StringUtils.isBlank(entrustVO.getSignUserId())) {
            return ResultVO.createError("签约用户ID为空!");
        }
        if(StringUtils.isBlank(entrustVO.getSignOrderNo())) {
            return ResultVO.createError("签约单号为空!");
        }
        if(StringUtils.isBlank(entrustVO.getPlanId())) {
            return ResultVO.createError("签约模板ID为空!");
        }
        return ResultVO.createSuccess();
    }

    @Override
    public ResultVO entrustPay(EntrustPayVO entrustPayVO) {
        log.info("EntrustPayApiImpl entrust pay start param:{}", JSONUtils.toJSON(entrustPayVO));
        try {
            // 参数检查
            ResultVO resultVO = checkEntrustPay(entrustPayVO);
            if(!ResultCodeEnum.SUCCESS.getCode().equalsIgnoreCase(resultVO.getCode())) {
                throw new PaymentException(resultVO.getMsg());
            }

            // 查询签约信息
            EntrustPayInfo param = new EntrustPayInfo();
            param.setSignUserId(entrustPayVO.getSignUserId());
            param.setSignOrderNo(entrustPayVO.getSignOrderNo());
            param.setStatus(EntrustStatusEnum.ENTRUST_SUCCESS.getCode());
            List<EntrustPayInfo> entrustList = entrustPayInfoService.selectByParam(param);
            if(entrustList.isEmpty()) {
                throw new PaymentException("无签约信息，扣款失败!");
            }
            EntrustPayInfo entrustInfo = entrustList.get(0);

            // 预支付订单创建
            PrepayDto prepayDto = new PrepayDto();
            prepayDto.setBusinessId(entrustPayVO.getBusinessUserId());
            prepayDto.setBusinessOrderNo(entrustPayVO.getBusinessOrderNo());
            prepayDto.setAmount(entrustPayVO.getAmount());
            prepayDto.setBusinessType(entrustPayVO.getBusinessType());
            prepayDto.setBusinessIdType(entrustPayVO.getBusinessOrderType());
            prepayDto.setOrderType(entrustPayVO.getBusinessOrderType());
            prepayDto.setBusinessOrderType(entrustPayVO.getBusinessOrderType());
            prepayDto.setCallbackUrl(entrustPayVO.getCallback());
            prepayDto.setChannel(Constants.CHANNEL_AGGREGATE_WX_NAME);
            prepayDto.setBody(entrustPayVO.getBody());
            prepayDto.setExtra(entrustPayVO.getMapJson());
            prepayDto.setContractCode(entrustInfo.getContractCode());
            resultVO = paymentService.prepay(prepayDto);
            if (!ResultCodeEnum.SUCCESS.getCode().equals(resultVO.getCode())){
                log.error("EntrustPayApiImpl entrustPay error prepayDto:{}, code:{}, msg:{}", JSON.toJSON(prepayDto), resultVO.getCode(), resultVO.getMsg());
                return resultVO;
            }
            PrepayBo prepayBo = (PrepayBo)resultVO.getResult();

            // 签约支付
            EntrustPayDto entrustPayDto = new EntrustPayDto();
            entrustPayDto.setPayNo(prepayBo.getPayNo());
            entrustPayDto.setBusinessType(entrustPayVO.getBusinessType());
            entrustPayDto.setBusinessOrderType(entrustPayVO.getBusinessOrderType());
            entrustPayDto.setBusinessOrderNo(entrustPayVO.getBusinessOrderNo());
            entrustPayDto.setAmount(entrustPayVO.getAmount());
            entrustPayDto.setCallback(entrustPayVO.getCallback());
            entrustPayDto.setChannel(entrustPayVO.getChannel().getCode());
            entrustPayDto.setPayMode(entrustPayVO.getPayMode().getMode());
            entrustPayDto.setSignOrderNo(entrustPayVO.getSignOrderNo());
            entrustPayDto.setSignUserId(entrustPayVO.getSignUserId());
            entrustPayDto.setBody(entrustPayVO.getBody());
            entrustPayDto.setMapJson(entrustPayVO.getMapJson());
            entrustPayDto.setInvoker(entrustPayVO.getInvoker());
            entrustPayDto.setBusinessUserId(entrustPayVO.getBusinessUserId());
            EntrustPayBO entrustPayBO = this.routeManager.entrustPay(entrustPayDto);
            log.info("EntrustPayApiImpl entrust pay end result:{}", JSONUtils.toJSON(entrustPayBO));
            return ResultVO.createSuccess(entrustPayBO);
        } catch (Exception e){
            log.error("EntrustPayApiImpl#entrustPay error. error:{}", e);
            return ResultVO.create(ResultCodeEnum.DEFAULT_ERROR);
        }

    }

    /**
     * 查询签约信息
     *
     * @param contractCode
     * @return
     */
    @Override
    public ResultVO queryEntrustInfo(String contractCode) {
        if(StringUtils.isBlank(contractCode)) {
            return ResultVO.createError("contractCode not be empty");
        }
        EntrustPayInfo entrustPayInfo = entrustPayInfoService.selectByContractCode(contractCode);
        EntrustInfoBo bo = new EntrustInfoBo();
        BeanUtils.copyProperties(entrustPayInfo,bo);
        return ResultVO.createSuccess(bo);
    }

    private ResultVO checkEntrustPay(EntrustPayVO entrustPayVO) {
        if(null == entrustPayVO) {
            return ResultVO.createError("参数为空!");
        }
        if(StringUtils.isBlank(entrustPayVO.getBusinessType())) {
            return ResultVO.createError("业务线标识为空");
        }
        if(StringUtils.isBlank(entrustPayVO.getBusinessOrderType())) {
            return ResultVO.createError("业务订单类型");
        }

        String accountId = payAccountService.getAccountIdByBusiness(entrustPayVO.getBusinessOrderType(), entrustPayVO.getBusinessUserId());
        if(StringUtils.isBlank(accountId)) {
            log.info("EntrustPayApiImpl account info is not found. entrustPayVO:{}", JSONUtils.toJSON(entrustPayVO));
            return ResultVO.createError("无收款方信息!");
        }

        if(null == entrustPayVO.getChannel()) {
            return ResultVO.createError("支付渠道为空!");
        }
        if(null == entrustPayVO.getPayMode()) {
            return ResultVO.createError("支付方式为空!");
        }
        if(StringUtils.isBlank(entrustPayVO.getSignUserId())) {
            return ResultVO.createError("签约用户ID为空!");
        }
        if(StringUtils.isBlank(entrustPayVO.getSignOrderNo())) {
            return ResultVO.createError("签约单号为空!");
        }
        if(StringUtils.isBlank(entrustPayVO.getBusinessOrderNo())) {
            return ResultVO.createError("业务订单号为空!");
        }
        if(null == entrustPayVO.getAmount()) {
            return ResultVO.createError("申请扣款金额为空!");
        }
        return ResultVO.createSuccess();
    }

}
